package com.zhiziai.aiproxy.utils;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.zone.ZoneRules;
import java.util.Calendar;
import java.util.Date;

/**
 * @Author lipeng
 * @Description 日期
 * @Date 2020/7/20 5:29 下午
 */
@Slf4j
public class DateUtils {
    private static final ThreadLocal<DateFormat> YMD = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
    public static final ThreadLocal<DateFormat> YMD1 = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));
    public static final ThreadLocal<DateFormat> YMD11 = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMddHHmm"));
    private static final ThreadLocal<DateFormat> YMD2 = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy.MM.dd"));
    private static final ThreadLocal<DateFormat> YMD_HM = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm"));
    public static final ThreadLocal<DateFormat> YMD_HMS = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    private static final ThreadLocal<DateFormat> YMD_HMS_SSS = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
    private static final ThreadLocal<DateFormat> HMS_SSS = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss.SSS"));
    private static final ThreadLocal<DateFormat> YMD_HMS2 = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy年MM月dd日"));
    private static final ThreadLocal<DateFormat> YMD_ZERO = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd 00:00:00"));
    private static final ThreadLocal<DateFormat> YMD_END = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd 23:59:59"));
    private static final ThreadLocal<DateFormat> YMD_FOUR_HOUR = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd 04:00:00"));
    private static final ThreadLocal<DateFormat> YMD_FIVE_HOUR = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd 05:00:00"));

    private static final ThreadLocal<SimpleDateFormat> YMD_HMS_SSSSSSSSS = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"));
    private static final ThreadLocal<SimpleDateFormat> HMS_SSSSSSSSS = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss.SSSSSSSSS"));

    private DateUtils(){

    }
    public static Date transStr2Date(String date) {
        try {
            return YMD.get().parse(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static Date transStr2Date(String date,ThreadLocal<DateFormat> formatThreadLocal) {
        try {
            return formatThreadLocal.get().parse(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static Date transStr2DateHMS(String date) {
        try {
            return YMD_HMS.get().parse(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static Date transStr2DateHM(String date) {
        try {
            return YMD_HM.get().parse(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static Date transStr2DateHMSSSS(String date) {
        try {
            return YMD_HMS_SSS.get().parse(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static Date transStr2NaSec(String date) {
        try {
            return YMD_HMS_SSSSSSSSS.get().parse(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static Date transDate2ZERO(Date date) {
        try {
            return YMD_ZERO.get().parse(transDate2StringYMDHMS(date));
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static String transDate2StringYMD2(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return YMD_HMS2.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }


    public static String transDate2String4H(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return YMD_FOUR_HOUR.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static String transDate2String5H(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return YMD_FIVE_HOUR.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static String transDate2StringYMD(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return YMD.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static String transDate2StringYMD1(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return YMD2.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }


    public static String transDate2StringYMDHMS(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return YMD_HMS.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }


    public static String transDate2StringHMSSSS(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return HMS_SSS.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static String transDate2StringNaSec(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return HMS_SSSSSSSSS.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static String transDate2StringYMDHM(Date date) {
        try {
            if (date == null) {
                return "";
            }
            return YMD_HM.get().format(date);
        } catch (Exception e) {
            log.error("查询失败", e);
        }
        return null;
    }

    public static String getNowDate() {
        return YMD.get().format(new Date());
    }

    public static String getTodayYMD() {
        return YMD1.get().format(new Date());
    }

    public static int getTodayDateInt() {
        return Integer.parseInt(YMD1.get().format(new Date()));
    }

    public static int getDateInt(Date date) {
        return Integer.parseInt(YMD1.get().format(date));
    }

    public static long getDateTimeInt(Date date) {
        return Long.parseLong(YMD11.get().format(date));
    }

    public static String getDateByInt(int dateInt) {
        Date date = transStr2Date(dateInt+"",YMD1);
        return transDate2StringYMD(date);
    }


    public static String getYesDate() {
        return transDate2StringYMD(getIntervalDate(new Date(),-1));
    }

    public static String getYesZero() {
        return YMD_ZERO.get().format(getIntervalDate(new Date(),-1));
    }

    public static String getNowMin() {
        return YMD_HM.get().format(new Date());
    }


    public static String getToday() {
        return YMD_ZERO.get().format(new Date());
    }

    public static String getTodayEnd() {
        return YMD_END.get().format(new Date());
    }

    /**
     * 得到距离几天前后的时间
     */
    public static Date getIntervalDate(Date date, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH, day);
        return cal.getTime();
    }

    public static Date getIntervalMin(Date date, int min) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, min);
        return cal.getTime();
    }

    public static Date getIntervalMonth(Date date, int month) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, month);
        return cal.getTime();
    }

    public static boolean isToday(Date date) {
        LocalDate now = LocalDate.now();
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
        return now.isEqual(localDate);
    }

    /**
     * 获取当前时间是春运的第几天
     *
     * @return
     */
    public static long getChunyunDay() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startDateTime = LocalDateTime.of(2021, 2, 27, 00, 00, 00);
        LocalDateTime endDateTime = LocalDateTime.of(2021, 3, 8, 23, 59, 59);
        if (now.isBefore(startDateTime) || now.isAfter(endDateTime)) {
            return -1;
        }
        return ChronoUnit.DAYS.between(startDateTime.toLocalDate(), now.toLocalDate()) + 1;
    }

    public static boolean isChunYunDay() {
        long day = getChunyunDay();
        if (day <= 0) {
            return false;
        }
        return true;
    }

    public static int getTodayLeftTime() {
        return (int) DateUtil.between(new Date(),DateUtil.endOfDay(new Date()), DateUnit.SECOND);
    }

    public static int differentDays(Date date1,Date date2){
        if (date1==null || date2==null){
            return 0;
        }
        return  (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24));
    }

    public static long differentSeconds(Date date1,Date date2){
        if (date1==null || date2==null){
            return 0;
        }
        return  (date2.getTime() - date1.getTime())/1000;
    }

    public static long differentMins(Date date1,Date date2){
        if (date1==null || date2==null){
            return 0;
        }
        return  (date2.getTime() - date1.getTime())/ (1000*60);
    }

    /**
     *  获取今天凌晨的时间
     * @return
     */
    public static Date getTodayMidnight(){
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        return cal.getTime();
    }

    /**
     *  获取今天凌晨的时间
     * @return
     */
    public static Date getMidnight(int beforeDays){
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)-beforeDays, 0, 0, 0);
        return cal.getTime();
    }

    /**
     * 获取指定日期几日之后的日期
     * @param n
     * @param date
     * @return
     */
    public static Date getDayAfter(int n,Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH,n);
        return cal.getTime();
    }

    public static boolean isDaylightSavings(LocalDateTime localDateTime){
        //还是以美国纽约时区为例
        ZoneId zoneId = ZoneId.of("America/New_York");
        //设置ZonedDateTime对象
        ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
        //获取时区计时规则
        ZoneRules rules = zoneId.getRules();
        //true表示处于夏令时，否则冬令时
        return rules.isDaylightSavings(zonedDateTime.toInstant());
    }


    public static LocalDateTime getUsDateTime(long mill){
        String dateTime = getUsDateTimeByMill(mill);
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        return LocalDateTime.parse(dateTime,df);
    }


    public static String getUsDateTimeByMill(long mill){
        ZoneId zoneId = ZoneId.of("America/New_York");
        LocalDateTime localDateTime = Instant.ofEpochMilli(mill).atZone(zoneId).toLocalDateTime();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        return df.format(localDateTime);
    }

    public static String getUsDateByMill(long mill){
        ZoneId zoneId = ZoneId.of("America/New_York");
        LocalDateTime localDateTime = Instant.ofEpochMilli(mill).atZone(zoneId).toLocalDateTime();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return df.format(localDateTime);
    }

    public static String getUsTimeByMill(long mill){
        ZoneId zoneId = ZoneId.of("America/New_York");
        LocalDateTime localDateTime = Instant.ofEpochMilli(mill).atZone(zoneId).toLocalDateTime();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
        return df.format(localDateTime);
    }

    public static void main(String[] args) {
//        System.out.println(LocalDateTime.now());
//        System.out.println(getChunyunDay());
//        System.out.println(isChunYunDay());
        Date date = transDate2ZERO(new Date());

    }

}
